Add options to discard filter to toss points based on regular expressions
authorrobertlipe <robertlipe@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Sun, 11 May 2014 23:42:53 +0000 (23:42 +0000)
committerrobertlipe <robertlipe@f51c46e8-681c-474f-0cfe-069cfd0219fb>
Sun, 11 May 2014 23:42:53 +0000 (23:42 +0000)
from name, cmt, desc, or icon.

This is something I've wanted to add for years.  Kolesár András sketched in
an implementation, but I went a different route.

gpsbabel/discard.cc
gpsbabel/reference/discardfields.gpx [new file with mode: 0644]
gpsbabel/xmldoc/filters/options/discard-matchcmt.xml [new file with mode: 0644]
gpsbabel/xmldoc/filters/options/discard-matchdesc.xml [new file with mode: 0644]
gpsbabel/xmldoc/filters/options/discard-matchicon.xml [new file with mode: 0644]
gpsbabel/xmldoc/filters/options/discard-matchname.xml [new file with mode: 0644]

index 7ed1d20f20b7197ce962ccb53be68235690546a7..5b9dfaf43d0f218fc17e7827cc4260d24f151ccf 100644 (file)
@@ -1,7 +1,7 @@
 /*
     Discard points based on high Degree of Precision (DOP) values.
 
-    Copyright (C) 2005 Robert Lipe, robertlipe+source@gpsbabel.org
+    Copyright (C) 2005-2014 Robert Lipe, robertlipe+source@gpsbabel.org
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -21,6 +21,8 @@
 
 #include "defs.h"
 #include "filterdefs.h"
+// Can't use QRegularExpression because Linux won't get Qt 5 for years. 
+#include <QtCore/QRegExp>
 
 #if FILTERS_ENABLED
 static char* hdopopt = NULL;
@@ -31,6 +33,15 @@ static char* fixnoneopt = NULL;
 static char* fixunknownopt = NULL;
 static char* eleminopt = NULL;
 static char* elemaxopt = NULL;
+static char* nameopt = NULL;
+static QRegExp name_regex;
+static char* descopt = NULL;
+static QRegExp desc_regex;
+static char* cmtopt = NULL;
+static QRegExp cmt_regex;
+static char* iconopt = NULL;
+static QRegExp icon_regex;
+
 static double hdopf;
 static double vdopf;
 static int satpf;
@@ -42,11 +53,11 @@ static route_head* head;
 static
 arglist_t fix_args[] = {
   {
-    "hdop", &hdopopt, "Suppress waypoints with higher hdop",
+    "hdop", &hdopopt, "Suppress points with higher hdop",
     "-1.0", ARGTYPE_BEGIN_REQ | ARGTYPE_FLOAT, ARG_NOMINMAX
   },
   {
-    "vdop", &vdopopt, "Suppress waypoints with higher vdop",
+    "vdop", &vdopopt, "Suppress points with higher vdop",
     "-1.0", ARGTYPE_END_REQ | ARGTYPE_FLOAT, ARG_NOMINMAX
   },
   {
@@ -54,25 +65,45 @@ arglist_t fix_args[] = {
     NULL, ARGTYPE_BOOL, ARG_NOMINMAX
   },
   {
-    "sat", &satopt, "Minimium sats to keep waypoints",
+    "sat", &satopt, "Minimium sats to keep points",
     "-1.0", ARGTYPE_BEGIN_REQ | ARGTYPE_INT, ARG_NOMINMAX
   },
   {
-    "fixnone", &fixnoneopt, "Suppress waypoints without fix",
+    "fixnone", &fixnoneopt, "Suppress points without fix",
     NULL, ARGTYPE_BOOL, ARG_NOMINMAX
   },
   {
-    "fixunknown", &fixunknownopt, "Suppress waypoints with unknown fix",
+    "fixunknown", &fixunknownopt, "Suppress points with unknown fix",
     NULL, ARGTYPE_BOOL, ARG_NOMINMAX
   },
   {
-    "elemin", &eleminopt, "Suppress waypoints below given elevation in meters",
+    "elemin", &eleminopt, "Suppress points below given elevation in meters",
     NULL, ARGTYPE_BEGIN_REQ | ARGTYPE_INT, ARG_NOMINMAX
   },
   {
-    "elemax", &elemaxopt, "Suppress waypoints above given elevation in meters",
+    "elemax", &elemaxopt, "Suppress points above given elevation in meters",
     NULL, ARGTYPE_BEGIN_REQ | ARGTYPE_INT, ARG_NOMINMAX
   },
+  {
+    "matchname", &nameopt,
+    "Suppress points where name matches given name", NULL, ARGTYPE_STRING,
+    ARG_NOMINMAX, NULL
+  },
+  {
+    "matchdesc", &descopt,
+    "Suppress points where description matches given name", NULL, ARGTYPE_STRING,
+    ARG_NOMINMAX, NULL
+  },
+  {
+    "matchcmt", &cmtopt,
+    "Suppress points where comment matches given name", NULL, ARGTYPE_STRING,
+    ARG_NOMINMAX, NULL
+  },
+  {
+    "matchicon", &iconopt,
+    "Suppress points where type matches given name", NULL, ARGTYPE_STRING,
+    ARG_NOMINMAX, NULL
+  },
   ARG_TERMINATOR
 };
 
@@ -121,6 +152,19 @@ fix_process_wpt(const Waypoint* wpt)
     del = 1;
   }
 
+  if (nameopt && name_regex.indexIn(waypointp->shortname) >= 0) {
+    del = 1;
+  }
+  if (descopt && desc_regex.indexIn(waypointp->description) >= 0) {
+    del = 1;
+  }
+  if (cmtopt && cmt_regex.indexIn(waypointp->notes) >= 0) {
+    del = 1;
+  }
+  if (iconopt && icon_regex.indexIn(waypointp->icon_descr) >= 0) {
+    del = 1;
+  }
+
   if (del) {
     switch (what) {
     case wptdata:
@@ -190,6 +234,11 @@ fix_init(const char* args)
   if (elemaxopt) {
     elemaxpf = atoi(elemaxopt);
   }
+
+  if (nameopt) {
+    name_regex.setCaseSensitivity(Qt::CaseInsensitive);
+    name_regex.setPattern(nameopt);
+  }
 }
 
 filter_vecs_t discard_vecs = {
diff --git a/gpsbabel/reference/discardfields.gpx b/gpsbabel/reference/discardfields.gpx
new file mode 100644 (file)
index 0000000..39c9bba
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- hand-crafted GPX file for exercising our discard filter -->
+<gpx version="1.0" creator="GPSBabel - http://www.gpsbabel.org" xmlns="http://www.topografix.com/GPX/1/0">
+  <time>1970-01-01T00:00:00Z</time>
+  <bounds minlat="35.972033333" minlon="-87.134700000" maxlat="36.090683333" maxlon="-86.679550000"/>
+  <wpt lat="35.972033333" lon="-87.134700000">
+    <name>1 One</name>
+    <cmt>1 One</cmt>
+    <desc>1 One</desc>
+  </wpt>
+  <wpt lat="36.090683333" lon="-86.679550000">
+    <name>name 2 Two</name>
+    <cmt>cmt 2 Two</cmt>
+    <desc>desc 2 Two</desc>
+  </wpt>
+  <wpt lat="36.090683333" lon="-86.679550000">
+    <name>name</name>
+    <cmt>cmt</cmt>
+    <desc>desc</desc>
+  </wpt>
+</gpx>
diff --git a/gpsbabel/xmldoc/filters/options/discard-matchcmt.xml b/gpsbabel/xmldoc/filters/options/discard-matchcmt.xml
new file mode 100644 (file)
index 0000000..e14cc64
--- /dev/null
@@ -0,0 +1,4 @@
+<para>
+Like <option>matchname</option>, but instead matches on the comment.
+</para>
+
diff --git a/gpsbabel/xmldoc/filters/options/discard-matchdesc.xml b/gpsbabel/xmldoc/filters/options/discard-matchdesc.xml
new file mode 100644 (file)
index 0000000..3aecb7a
--- /dev/null
@@ -0,0 +1,3 @@
+<para>
+Like <option>matchname</option>, but instead matches on the description.
+</para>
diff --git a/gpsbabel/xmldoc/filters/options/discard-matchicon.xml b/gpsbabel/xmldoc/filters/options/discard-matchicon.xml
new file mode 100644 (file)
index 0000000..aac835d
--- /dev/null
@@ -0,0 +1,3 @@
+<para>
+Like <option>matchname</option>, but instead matches on the icon description.
+</para>
diff --git a/gpsbabel/xmldoc/filters/options/discard-matchname.xml b/gpsbabel/xmldoc/filters/options/discard-matchname.xml
new file mode 100644 (file)
index 0000000..5ee8e5d
--- /dev/null
@@ -0,0 +1,17 @@
+<para>
+This option discards points that have shortnames that match the 
+provided regular expresision.
+</para>
+<example id="discarding_points_with_names">
+<title>Discarding specific point by regular expression</title>
+<para>
+For example geocaches typically have names starting with GC followed
+by an alphanumeric sequence of variable length.  To remove all six character
+long IDs that between (and including) GC1000 and GC2FFF, you could use
+</para>
+<para><userinput>
+gpsbabel -i geo -f geocaching.loc -x discard,matchname=GC[1-2]...
+</userinput>
+to discard all GCs followed by exactly three characters.
+</para>
+</example>